// C source file with the function definitions to handle BTP data

// check_j3dgraph_btp() function
// function to check if a J3DGraph BTP is valid
j3dgraph_t check_j3dgraph_btp(char * fpath)
{
  // use open_j3dgraph_inc() to check the file (it is needed anyways)
  j3dgraph * file = open_j3dgraph_inc(fpath);
  if (file == NULL)
    goto err;
  // check the header and the sections of the BMD/BDL
  // starting array
  if (comp_bytes(file -> HEADER.ID, J3DGRAPH_BTP_ID[file -> ENDIAN - 1], 4) == false)
    goto err;  
  // check section count, considering the file type
  if (get_std_uint(32, file -> HEADER.SEC_CNT, file -> ENDIAN) != J3DGRAPH_BTP_SEC_CNT)
    goto err;
  
  // Unknown 1 does not have to be checked to be honest...
    
  // section checks (only 1 for a BTP)
  if (check_j3dgraph_btp_tpt1(file) < J3DGRAPH_BTP_TPT1_ERR_NO_ERR)
    goto err;
  
  // all good
  close_j3dgraph_inc(file);
  return J3DGRAPH_BTP;
  
  // invalid section
  err:
  close_j3dgraph_inc(file);
  return J3DGRAPH_NO_TYPE;
}

// open_j3dgraph_btp() function
// open a BTP (build a complete j3dgraph struct for BTP)
j3dgraph * open_j3dgraph_btp(char * fpath)
{
  // check if the header/sections are valid
  j3dgraph * file = NULL;
  void * tmp = NULL;
  // check if it is a BTP type
  if (check_j3dgraph_btp(fpath) == J3DGRAPH_NO_TYPE)
    goto err;
  // open an incomplete j3dgraph struct and add the TPT1 section to it
  file = open_j3dgraph_inc(fpath);
  file -> TYPE = J3DGRAPH_BTP;
  
  // build a complete j3dgraph BTP structure
  if ((tmp = append_j3dgraph_btp_tpt1(file)) == NULL)
    goto err;
    
  // all went good
  return file;
  // failure
  err:
  free_memory(tmp);
  close_j3dgraph_inc(file);
  return NULL;
}

// close_j3dgraph_btp() function
// function to close a complete j3dgraph BTP structure (free it)
void close_j3dgraph_btp(j3dgraph * file)
{
  // free the memory allocated by all functions
  if (file == NULL || file -> TYPE != J3DGRAPH_BTP)
    return;
  
  // sections
  remove_j3dgraph_btp_tpt1(file);  
  // j3dgraph structure
  close_j3dgraph_inc(file);
  
  // all done!
  return;
}

// print_j3dgraph_btp() function
// print the information of a J3DGraph BTP
void print_j3dgraph_btp(j3dgraph * file)
{
  // print everything header and sections
  // check ptr
  if (file == NULL)
    return;
  
  // starting visual queue
  printf("\n### J3DGraph BTP struct info start ###\n\n");
  
  // print the start of the j3dgraph struct
  print_j3dgraph_start(file);
  
  // section
  print_j3dgraph_btp_tpt1((j3dgraph_btp_tpt1 *) ((file -> SEC)[J3DGRAPH_BTP_TPT1_POS]));
  
  // end of structure
  printf("\n### J3DGraph BTP struct info end ###\n");
  return; 
}

// check_j3dgraph_btp_agst_bmd_bdl() function
// function to check if a j3dgraph BTP is compatible with a j3dgrap BMD/BDL 
bool check_j3dgraph_btp_agst_bmd_bdl(char * btp_path, char * bmd_bdl_path)
{
  bool result = true;
  j3dgraph * btp = NULL, * bmd_bdl = NULL;
  // check params
  if (btp_path == NULL || bmd_bdl_path == NULL)
    goto end;
  
  // check j3dgraph structures
  btp = open_j3dgraph_btp(btp_path);
  bmd_bdl = open_j3dgraph_bmd_bdl(bmd_bdl_path);
  if (btp == NULL || bmd_bdl == NULL)
    goto end;
  
  // check tpt1 section agaisnt the mat3 and tex1 sections
  j3dgraph_btp_tpt1 * tpt1 = (btp -> SEC)[J3DGRAPH_BTP_TPT1_POS];
  // J3DGRAPH_BMD_MAT3_POS == J3DGRAPH_BDL_MAT3_POS is true
  j3dgraph_bmd_mat3 * mat3 = (bmd_bdl -> SEC)[J3DGRAPH_BMD_MAT3_POS];
  umax tex1_pos = bmd_bdl -> TYPE == J3DGRAPH_BMD ? J3DGRAPH_BMD_TEX1_POS : J3DGRAPH_BDL_TEX1_POS;
  j3dgraph_bmd_tex1 * tex1 = (bmd_bdl -> SEC)[tex1_pos];
  if (check_j3dgraph_btp_tpt1_agst_bmd_bdl_mat3_tex1(tpt1, mat3, tex1) < J3DGRAPH_BTP_TPT1_ERR_NO_ERR)
    result = false;
  
  // close files
  end:
  close_j3dgraph_btp(btp);
  close_j3dgraph_bmd_bdl(bmd_bdl);
  return result;
}

//~ // WRITE_CSV_BTP() function
//~ // function to write the CSV version of the BTP (based on the j3d-animation-editor format)
//~ void WRITE_CSV_BTP(char  * btp_fpath)
//~ {
  //~ // CSV BTP description
  
  //~ // loop mode, general animation length, 0, .btp                           (header 1st line)
  //~ // Material Name,Duration, Frame 1, ... Keyframe numbers ...              (header 2nd line)
  //~ // Mat 1 name, Mat 1 anim length, Frame 1 value, ... Keyframe values ...  (contents)
  //~ // ...
  
  //~ // load BTP file in memory
  //~ Jbtp * BTP = OPEN_BIN_BTP(btp_fpath);
  
  //~ // mask variables so they aren't that 
  //~ // long to read in this program block
  //~ byte *    DATA   = BTP -> RAW_DT;
  //~ ENDIAN_T    ENDIAN = BTP -> ENDIAN;
  //~ Jbtp_ptr_tb PTR_TB = * BTP -> PTR_TB;
  
  //~ // get the csv file name
  //~ char * csv_fpath = allocate_memory(get_str_length(btp_fpath, 0) + 4, 1);
  //~ char * ext_pos = join_strings(btp_fpath, csv_fpath);
  //~ join_strings(".csv", ext_pos);
  
  //~ // create the sacred CSV BTP file
  //~ FILE * fp = def_fopen(csv_fpath, "w");
  
  //~ umax loop_mode = GET_DATA_T(1, U_INT, DATA + PTR_TB.LOOP_MODE, NULL, ENDIAN);
  //~ umax anim_length = GET_DATA_T(2, U_INT, DATA + PTR_TB.LAST_ANIM_FRAME, NULL, ENDIAN);
  //~ umax mat_count = GET_DATA_T(2, U_INT, DATA + PTR_TB.ANIM_MAT_CNT, NULL, ENDIAN);
  
  //~ // CSV header
  //~ fprintf(fp, "%llu,%llu,0,.btp\n", loop_mode, anim_length);
  
  //~ // CSV second line after header
  //~ // get the animation length of all materials
  //~ umax * mat_anim_length = allocate_memory(mat_count, sizeof(umax));  
  //~ umax max_kf_value = 0;
  //~ for (smax_t i = 0; i < mat_count; i++)
  //~ {
    //~ mat_anim_length[i] = GET_DATA_T(2, U_INT, DATA + PTR_TB.ANIM_TABLE + (i * 8), NULL, ENDIAN);
    //~ if (max_kf_value < mat_anim_length[i])
      //~ max_kf_value = mat_anim_length[i];
  //~ }  
  //~ // get all the keyframes of the animation
  //~ // need to go through the last frame with 
  //~ // animation data for each material
  //~ bool * anim_keyframes = allocate_memory(max_kf_value, sizeof(bool));  
  //~ for (smax_t i = 0; i < mat_count; i++)
  //~ {    
    //~ // get the animation data position of the 
    //~ // material to be read on the texture swap table
    //~ umax mat_tex_swap_data_pos = GET_DATA_T(2, U_INT, DATA + PTR_TB.ANIM_TABLE + (i * 8) + 2, NULL, ENDIAN);
    
    //~ // variables to check the keyframes 
    //~ // of the material animation
    //~ umax current_tex_number = 0;
    //~ umax old_tex_number = 0;    
    //~ for (smax_t j = 0; j < mat_anim_length[i]; j++)
    //~ {      
      //~ // get current texture swap number
      //~ current_tex_number = GET_DATA_T(2, U_INT, DATA + PTR_TB.TEX_SWAP_TABLE + (j * 2) + mat_tex_swap_data_pos, NULL, ENDIAN);
      
      //~ // frame 0 is always a keyframe
      //~ if (j == 0)
      //~ {
        //~ anim_keyframes[0] = true;
        //~ old_tex_number = current_tex_number;
        //~ continue;
      //~ }
      
      //~ // if there is a texture transition that 
      //~ // means that the current frame is a keyframe
      //~ if (current_tex_number == old_tex_number)
        //~ continue;
      //~ else
        //~ // frame j is a keyframe
        //~ anim_keyframes[j] = true;
        
      //~ old_tex_number = current_tex_number;     
    //~ }
    
    //~ // always add last frame of each material's animation
    //~ // data as a keyframe (it helps to avoid confusion)
    //~ anim_keyframes[mat_anim_length[i] - 1] = true;
  //~ }
  
  //~ // write the second line (finally lol!)
  //~ fprintf(fp, "Material Name,Duration");
  //~ for (smax_t i = 0; i < max_kf_value; i++)
    //~ if (anim_keyframes[i] == true)
      //~ fprintf(fp, ",Frame %llu", i);
  //~ fprintf(fp, "\n");
  
  //~ // write contents: Material name, Last Frame With Anim Data, keyframe texture values...
  //~ umax str_array_current_pos = 0;
  //~ for (smax_t i = 0; i < mat_count; i++)
  //~ {
    //~ // get material data animation position on the tex swap table
    //~ umax tex_swap_table_current_pos = 2 *  GET_DATA_T(2, U_INT, DATA + PTR_TB.ANIM_TABLE + (i * 8) + 2, NULL, ENDIAN);
    
    //~ // write material name and its animation length (last frame with animation data)  
    //~ fprintf(fp, "%s,%llu", DATA + PTR_TB.MAT_NAME_LIST + str_array_current_pos, mat_anim_length[i]);
    
    //~ // advance to the start of the next material name string
    //~ str_array_current_pos += get_str_length(DATA + PTR_TB.MAT_NAME_LIST + str_array_current_pos, 0);
    
    //~ // write texture values for the keyframes using the animation_keyframes array
    
    //~ // keep track of current texture number and the texture 
    //~ // number from before to avoid writing repeated data
    //~ umax current_tex_number = 0;
    //~ umax old_tex_number = 0;
    //~ for (smax_t j = 0; j < mat_anim_length[i]; j++)
    //~ {
      //~ // ignore non-keyframe frames
      //~ if (anim_keyframes[j] == false)
        //~ continue;
      
      //~ // get current texture number
      //~ current_tex_number = GET_DATA_T(2, U_INT, DATA + PTR_TB.TEX_SWAP_TABLE + tex_swap_table_current_pos + (j * 2), NULL, ENDIAN);
      
      //~ // if there is a texture number transition
      //~ // on the keyframe update old_tex_number and
      //~ //last_rel_kf_num for the next loop and 
      //~ if (old_tex_number != current_tex_number)
        //~ old_tex_number = current_tex_number;
    //~ }
    
    //~ // reset old_tex_number for the next loop
    //~ old_tex_number = 0;
    
    //~ // write material texture swap animation data
    //~ for (smax_t j = 0; j < mat_anim_length[i]; j++)
    //~ {
      //~ // avoid non-keyframe frames
      //~ if (anim_keyframes[j] == false)
        //~ continue;
      
      //~ // get current texture number
      //~ current_tex_number = GET_DATA_T(2, U_INT, DATA + PTR_TB.TEX_SWAP_TABLE + tex_swap_table_current_pos + (j * 2), NULL, ENDIAN);
      
      //~ // check if current_tex_number is required to be written
      //~ if (j == 0 || old_tex_number != current_tex_number)
        //~ fprintf(fp, ",%llu", current_tex_number);
      //~ else
        //~ fprintf(fp, ",");
      
      //~ // get the new old_tex_number for the next loop
      //~ old_tex_number = current_tex_number;
    //~ }
    
    //~ // end line on CSV BTP
    //~ fprintf(fp, "\n");
  //~ }
    
  //~ // BTP file has been converted to its CSV equivalent!
  //~ printf("\nFile %s has been created.\n", csv_fpath);
  //~ def_fclose(fp); 
  
  //~ // free memory used on this function
  //~ CLOSE_BIN_BTP(BTP);
  //~ free_memory(csv_fpath);
  //~ free_memory(mat_anim_length);
  //~ free_memory(anim_keyframes);
  
  //~ return;
//~ }
